package org.keyintegrity.webbeans.metadata.store;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.keyintegrity.webbeans.metadata.BeanMetadata;

public abstract class AbstractStore implements MetadataStore, Serializable {

    private final Map<String, BeanMetadata> loadedMetadata;

    public AbstractStore() {
        loadedMetadata = new HashMap<String, BeanMetadata>();
    }
    
    public abstract BeanMetadata newBeanMetadata();

    public String getName() {
        return toString();
    }
    
    public void setName(String name) {
        //  Nothing
    }
    
    public void removeMetadata(BeanMetadata metadata) {
        loadedMetadata.remove(metadata.getAssociatedClass());
    }
    
    public BeanMetadata lookupBeanMetadataForClass(Class clazz) throws MetadataStoreException {
        if (clazz == null || clazz.equals(Object.class)) {
            return null;
        }
        
        BeanMetadata result = loadedMetadata.get(clazz);
        if (result == null) {
            try {
                result = loadMetadata(clazz.getName());
                loadedMetadata.put(clazz.getName(), result);
            } catch (MetadataNotFoundException e) {
                //  Try lookup by clazz's interfaces and superclasses
                for (Class intf : clazz.getInterfaces()) {
                    result = lookupBeanMetadataForClass(intf);
                    if (result != null) {
                        break;
                    }
                }
                if (result == null) {
                    result = lookupBeanMetadataForClass(clazz.getSuperclass());
                }
            }
        }
        return result;
    }
    
    public final BeanMetadata acquireBeanMetadataForClass(Class clazz) throws MetadataStoreException {
        BeanMetadata result = lookupBeanMetadataForClass(clazz); 
        if (result == null) {
            result = newBeanMetadata();
            result.setAssociatedClass(clazz.getName());
            loadedMetadata.put(clazz.getName(), result);
        }
        return result;
    }
    
}